package org.jtb.quickr;

import java.util.Date;
import java.util.Set;

/**
 * Criteria for searching photos using the 
 * <CODE>PhotoService.search()</CODE> method.
 * This class is a bean that encapsulates all of the arguments for searching
 * photos in a type safe manner. 
 * For details, see the
 * <a href="http://www.flickr.com/services/api/flickr.photos.search.html">
 * flickr.photos.search service</a> documentation.
 *
 * @see org.jtb.quickr.PhotosService#search(AuthResponse.Token,PhotosSearchCriteria)
 */
public class PhotosSearchCriteria {
    /**
     * Tag mode.
     */
    public enum TagMode {
        ALL ("all"),
        ANY ("any");

        private String s;
        
        private TagMode(String s) {
            this.s = s;
        }     
        
        public String toString() {
            return s;
        }
    }
    
    /**
     * Sort type for results.
     */
    public enum Sort {
        DATE_POSTED_ASCENDING ("date-posted-asc"),
        DATE_POSTED_DESCENDING ("date-posted-desc"),
        DATE_TAKEN_ASCENDING ("date-taken-asc"),
        DATE_TAKEN_DESCENDING ("date-taken-desc"),
        INTERESTINGNESS_ASCENDING ("interestingness-asc"),
        INTERESTINGNESS_DESCENDING ("interestingness-desc"),
        RELEVANCE ("relevance");
        
        private String s;
        
        private Sort(String s) {
            this.s = s;
        }
        
        public String toString() {
            return s;
        }
    }

    /**
     * Privacy filter.
     */
    public enum PrivacyFilter {
        PUBLIC ("1"),
        FRIENDS ("2"),
        FAMILY ("3"),
        FRIENDS_FAMILY ("4"),
        PRIVATE ("5");
        
        private String s;
        
        private PrivacyFilter(String s) {
            this.s = s;
        }

        public String toString() {
            return s;
        }
        
    }
    
    /**
     * Bounding box. Values must be between -180,180 and -90,90. Setting values
     * outside of this range causes them to be rounded up for down as 
     * appropriate.
     */
    public static class BoundingBox {
        private int maxLong = 180;
        private int minLong = -180;
        private int maxLat = 90;
        private int minLat = -90;

        public int getMaxLong() {
            return maxLong;
        }

        public void setMaxLong(int maxLong) {
            this.maxLong = Math.min(maxLong, 180);
        }

        public int getMinLong() {
            return minLong;
        }

        public void setMinLong(int minLong) {
            this.minLong = Math.max(minLong, -180);
        }

        public int getMaxLat() {
            return maxLat;
        }

        public void setMaxLat(int maxLat) {
            this.maxLat = Math.min(maxLat, 90);
        }

        public int getMinLat() {
            return minLat;
        }

        public void setMinLat(int minLat) {
            this.minLat = Math.max(minLat, -90);
        }        
        
        public String toString() {
            return getMinLong() + "," + getMinLat() + "," + getMaxLong() + "," + getMaxLat();
        }
    }
    
    /**
     * Location accuracy.
     */
    public enum LocationAccuracy {
        MAX ("1"),
        WORLD ("1"),
        COUNTRY ("3"),
        REGION ("6"),
        CITY ("11"),
        STREET ("16"),
        MIN ("16");
        
        private String s;
        
        private LocationAccuracy(String s) {
            this.s = s;
        }
    
        public String toString() {
            return s;
        }

    }
    
    /**
     * Extra fields for results.
     */
    public enum Extra {
        LICENSE_DATE ("license_date"),
        UPLOAD_DATE ("upload_date"),
        DATE_TAKEN ("date_taken"),
        OWNER_NAME ("owner_name"),
        ICON_SERVER ("icon_server"),
        ORIGINAL_FORMAT ("original_format"),
        LAST_UPDATE ("last_update"),
        TAGS ("tags"),
        MACHINE_TAGS ("machine_tags"),
        O_DIMS ("o_dims"),
        VIEWS ("views"),
        MEDIA ("media");

        private String s;
        
        private Extra(String s) {
            this.s = s;
        }

        public String toString() {
            return s;
        }
    }
    
    private Set<String> tags;
    private TagMode tagMode;
    private String text;
    private Date minUploadDate;
    private Date maxUploadDate;
    private Date minTakenDate;
    private Date maxTakenDate;
    private Set<String> licenses;
    private Sort sort;
    private PrivacyFilter privacyFilter;
    private BoundingBox boundingBox;
    private LocationAccuracy locationAccuracy;
    private Set<Extra> extras;
    private Integer perPage;
    private Integer page;
    private String userId;
    
    public Set<String> getTags() {
        return tags;
    }

    public void setTags(Set<String> tags) {
        this.tags = tags;
    }

    public TagMode getTagMode() {
        return tagMode;
    }

    public void setTagMode(TagMode tagMode) {
        this.tagMode = tagMode;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Date getMinUploadDate() {
        return minUploadDate;
    }

    public void setMinUploadDate(Date minUploadDate) {
        this.minUploadDate = minUploadDate;
    }

    public Date getMaxUploadDate() {
        return maxUploadDate;
    }

    public void setMaxUploadDate(Date maxUploadDate) {
        this.maxUploadDate = maxUploadDate;
    }

    public Date getMinTakenDate() {
        return minTakenDate;
    }

    public void setMinTakenDate(Date minTakenDate) {
        this.minTakenDate = minTakenDate;
    }

    public Date getMaxTakenDate() {
        return maxTakenDate;
    }

    public void setMaxTakenDate(Date maxTakenDate) {
        this.maxTakenDate = maxTakenDate;
    }

    public Set<String> getLicenses() {
        return licenses;
    }

    public void setLicenses(Set<String> licenses) {
        this.licenses = licenses;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public Sort getSort() {
        return sort;
    }

    public void setSort(Sort sort) {
        this.sort = sort;
    }

    public PrivacyFilter getPrivacyFilter() {
        return privacyFilter;
    }

    public void setPrivacyFilter(PrivacyFilter privacyFilter) {
        this.privacyFilter = privacyFilter;
    }

    public BoundingBox getBoundingBox() {
        return boundingBox;
    }

    public void setBoundingBox(BoundingBox boundingBox) {
        this.boundingBox = boundingBox;
    }

    public LocationAccuracy getLocationAccuracy() {
        return locationAccuracy;
    }

    public void setLocationAccuracy(LocationAccuracy locationAccuracy) {
        this.locationAccuracy = locationAccuracy;
    }

    public Set<Extra> getExtras() {
        return extras;
    }

    public void setExtras(Set<Extra> extras) {
        this.extras = extras;
    }

    public Integer getPerPage() {
        return perPage;
    }

    public void setPerPage(Integer perPage) {
        this.perPage = perPage;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }    
}
